<script lang="ts" setup>
import type { EChartsOption } from 'echarts'
import echarts from '@/plugins/echarts'
import { debounce, merge } from 'lodash-es'
import 'echarts-wordcloud'
import { propTypes } from '@/utils/propTypes'
import { PropType } from 'vue'
import { useAppStore } from '@/store/modules/app'
import { isString } from '@/utils/is'
import { useDesign } from '@/hooks/web/useDesign'

import 'echarts/lib/component/markPoint'
import 'echarts/lib/component/markLine'
import 'echarts/lib/component/markArea'
import { ScatterChart } from 'echarts/charts'
echarts.use([ScatterChart])

defineOptions({ name: 'EChart' })

const { getPrefixCls, variables } = useDesign()

const prefixCls = getPrefixCls('echart')

const appStore = useAppStore()

const props = defineProps({
  options: {
    type: Object as PropType<EChartsOption>,
    required: true
  },
  width: propTypes.oneOfType([Number, String]).def(''),
  height: propTypes.oneOfType([Number, String]).def('500px'),
  notMerge: propTypes.bool.def(true), // 是否非合并模式
  useEchartTitle: propTypes.bool.def(false) // 是否使用echart的title
})

const isDark = computed(() => appStore.getIsDark)

const theme = computed(() => {
  const echartTheme: boolean | string = unref(isDark) ? true : 'auto'

  return echartTheme
})

const options: any = computed(() => {
  if (!props.useEchartTitle) {
    return merge(props.options, {
      title: {
        show: false
      }
    })
  }
  return Object.assign(props.options, {
    darkMode: unref(theme)
  })
})

const elRef = ref<ElRef>()

let echartRef: Nullable<echarts.ECharts> = null

const contentEl = ref<Element>()

const styles = computed(() => {
  const width = isString(props.width) ? props.width : `${props.width}px`
  const height = isString(props.height) ? props.height : `${props.height}px`

  return {
    width,
    height
  }
})
const isDataEmpty = computed(() => {
  return !options.value?.series?.some((item) => {
    return item?.data?.length
  })
})
const initChart = () => {
  if (unref(elRef) && props.options) {
    echartRef = echarts.init(unref(elRef) as HTMLElement)
    echartRef?.setOption(unref(options))
  }
}

watch(
  () => options.value,
  (options) => {
    setTimeout(() => {
      if (!isDataEmpty.value) {
        if (!echartRef) {
          initChart()
        }
      } else {
        if (echartRef) {
          echartRef.dispose()
          echartRef = null
        }
      }
      if (echartRef) {
        echartRef?.setOption(options, props.notMerge)
        echartRef?.resize()
      }
    }, 0)
  },
  {
    deep: true
  }
)

const resizeHandler = debounce(() => {
  if (echartRef) {
    echartRef.resize()
  }
}, 100)

const contentResizeHandler = async (e: TransitionEvent) => {
  if (e.propertyName === 'width') {
    resizeHandler()
  }
}

onMounted(() => {
  initChart()

  window.addEventListener('resize', resizeHandler)

  contentEl.value = document.getElementsByClassName(`${variables.namespace}-layout-content`)[0]
  unref(contentEl) &&
    (unref(contentEl) as Element).addEventListener('transitionend', contentResizeHandler)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeHandler)
  unref(contentEl) &&
    (unref(contentEl) as Element).removeEventListener('transitionend', contentResizeHandler)
})

onActivated(() => {
  if (echartRef) {
    echartRef.resize()
  }
})
</script>

<template>
  <div :style="!useEchartTitle && isDataEmpty && styles">
    <div
      v-if="!useEchartTitle && options?.title?.text"
      :class="[
        'echart-title text-#333 text-18px',
        {
          'text-center': options?.title.left === 'center',
          'text-left': options?.title.left === 'left',
          'text-right': options?.title.left === 'right'
        }
      ]"
      >{{ options?.title?.text }}</div
    >
    <div v-if="!isDataEmpty" ref="elRef" :class="[$attrs.class, prefixCls]" :style="styles"> </div>
    <div v-else class="mt-30px">
      <el-empty :image-size="100" description="暂无数据" />
    </div>
  </div>
</template>
